package cn.bonoon.services.plugins;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.bonoon.core.plugins.RecycleServcie;
import cn.bonoon.entities.plugins.RecycleEntity;
import cn.bonoon.handler.DefaultRecycleHandler;
import cn.bonoon.handler.RecycleHandler;
import cn.bonoon.kernel.events.OperateEvent;
import cn.bonoon.kernel.support.services.AbstractSearchService;
import cn.bonoon.kernel.util.StringHelper;

@Service
@Transactional(readOnly = true)
public class RecycleServiceImpl extends AbstractSearchService<RecycleEntity> implements RecycleServcie {

	private final static String HANDLER_SUFFIX = "RecycleHandlerImpl";
	private static final char PACKAGE_SEPARATOR_CHAR = '.';
	private final static RecycleHandler DEFAULT_RECYCLE_HANDLER = new DefaultRecycleHandler();
	private final Map<String, RecycleHandler> handlers = new ConcurrentHashMap<String, RecycleHandler>();

	private final static String ENTITY_SUFFIX = "Entity";

	private RecycleHandler getHandler(String entityName) {
		RecycleHandler recycle = null;
		if (handlers.containsKey(entityName)) {
			recycle = handlers.get(entityName);
			if (null != recycle)
				return recycle;
		}
		if (StringHelper.isNotEmpty(entityName)) {
			int lastDotIdx = entityName.lastIndexOf(PACKAGE_SEPARATOR_CHAR);
			int endIndex = entityName.length();
			if (entityName.endsWith(ENTITY_SUFFIX))
				endIndex -= ENTITY_SUFFIX.length();
			String n = entityName.substring(lastDotIdx + 1, endIndex);
			String name = n + HANDLER_SUFFIX;
			if (applicationContext.containsBean(name))
				recycle = applicationContext.getBean(name, RecycleHandler.class);
		}
		if (null == recycle)
			recycle = DEFAULT_RECYCLE_HANDLER;

		handlers.put(entityName, recycle);
		return recycle;
	}
//	protected final <B> B getBeanOrNull(String name, Class<B> requiredType) throws BeansException {
//	if (applicationContext.containsBean(name))
//		return applicationContext.getBean(name, requiredType);
//	return null;
//}
	
//	@Override
//	@Transactional
//	public void delete(IOperator optor, Long id) {
//		RecycleEntity entity = get(id);
//		delete(entity);
//	}
//
//	private void delete(RecycleEntity entity) {
//		if (null != entity) {
//			String entityName = entity.getEntityName();
//			getHandler(entityName).delete(getEntityManager(), entity);
//		}
//	}
//
//	private void resume(RecycleEntity entity) {
//		if (null != entity) {
//			String entityName = entity.getEntityName();
//			getHandler(entityName).resume(getEntityManager(), entity);
//		}
//	}
//
//	@Override
//	@Transactional
//	public void delete(IOperator optor, Long... ids) {
//		for (Long id : ids) {
//			delete(optor, id);
//		}
//	}
//
//	@Override
//	@Transactional
//	public void resume(Long id) {
//		RecycleEntity entity = get(id);
//		resume(entity);
//	}
//
//	@Override
//	@Transactional
//	public void resume(Long... ids) {
//		for (Long id : ids) {
//			resume(id);
//		}
//	}

	private final static String SELECT_STATEMENT = "select x from RecycleEntity as x";

	@Override
	@Transactional
	public Object operate(int operand, OperateEvent event, Long id) {
		return operate_single(operand, event, id);
	}
	
	private Object operate_single(int operand, OperateEvent event, Long id) {
		RecycleEntity entity = __get(event.decryptId(id));
		scopeFilter.check(event, entity);
		Long eid = entity.getEntityId();
		String ename = entity.getEntityName();
		switch (operand) {
		case RecycleServcie.DELETE:
			entity.setDeleted(true);
			entityManager.merge(entity);
			break;
		case RecycleServcie.REMOVE:
			String remove_sql = String.format("delete from %s where id = %d and deleted=true", ename, eid);
			entityManager.createQuery(remove_sql).executeUpdate();
			entityManager.remove(entity);
			break;
		case RecycleServcie.RESUME:
			String resume_sql = String.format("update %s set deleted = false where id = %d", ename, eid);
			entityManager.createQuery(resume_sql).executeUpdate();
			entityManager.remove(entity);
			break;
		default:
			break;
		}
		return id;
	}

	@Override
	@Transactional
	public Object operate(int operand, OperateEvent event, Long... ids) {
		String ql = "select x from RecycleEntity as x where x.deleted=false";
		switch (operand) {
		case RecycleServcie.DELETE:
		case RecycleServcie.REMOVE:
		case RecycleServcie.RESUME:
			if (null != ids && ids.length > 0) {
				for (Long id : ids) {
					operate_single(operand, event, id);
				}
			}
			break;
		case RecycleServcie.CLEARALL:
			List<RecycleEntity> entitys = __list(domainClass, ql);
			if (null != entitys && entitys.size() > 0) {
				for (RecycleEntity entity : entitys) {
					scopeFilter.check(event, entity);
					entity.setDeleted(true);
					entityManager.merge(entity);
				}
			}
			break;
		case RecycleServcie.REMOVEALL:
			List<RecycleEntity> removeall_entitys = __list(domainClass, ql);
			if (null != removeall_entitys && removeall_entitys.size() > 0) {
				for (RecycleEntity entity : removeall_entitys) {
					scopeFilter.check(event, entity);
					Long eid = entity.getEntityId();
					String ename = entity.getEntityName();
					String sql = String.format("delete from %s where id = %d and deleted=true", ename, eid);
					entityManager.createQuery(sql).executeUpdate();
					entityManager.remove(entity);
				}
			}
			break;
		default:
			break;
		}
		return ids;
	}

}
